package com.zmn.oms.dubbo.impl.zmn.normal.order;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zmn.base.pilot.common.dto.pilot.PilotCheckQuery;
import com.zmn.base.pilot.common.enums.PilotTypeEnum;
import com.zmn.base.pilot.dubbo.interfaces.pilot.PilotRemoteService;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.constant.OrderGlobalConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.common.utils.validator.ValidateResult;
import com.zmn.common.utils.validator.ValidatorUtil;
import com.zmn.dms.common.enums.DiscountTypeEnums;
import com.zmn.oms.business.interfaces.apply.CancelApplyBService;
import com.zmn.oms.business.interfaces.es.OrderWorkEsBService;
import com.zmn.oms.business.interfaces.log.OrderLogBService;
import com.zmn.oms.business.interfaces.orderamount.OrderDiscountCalcBService;
import com.zmn.oms.business.interfaces.warranty.OrderWarrantyBService;
import com.zmn.oms.business.interfaces.work.OrderWorkListBService;
import com.zmn.oms.business.interfaces.worktrack.WorkTrackBService;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.constant.OrderStatusConsts;
import com.zmn.oms.common.constant.OrderTagConsts;
import com.zmn.oms.common.dro.tag.OrderTagDRO;
import com.zmn.oms.common.enums.EncryptFieldTypeEnum;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.common.utils.TimeTextUtil;
import com.zmn.oms.dubbo.dto.common.work.OrderDetailDiscountDRO;
import com.zmn.oms.dubbo.dto.common.work.TrackModifyDutyTimeDIO;
import com.zmn.oms.dubbo.dto.zmn.order.*;
import com.zmn.oms.dubbo.dto.zmn.order.user.UserListOrderQueryDIO;
import com.zmn.oms.dubbo.dto.zmn.order.user.UserOrderPageDRO;
import com.zmn.oms.dubbo.dto.zmn.order.user.UserOrderQueryDIO;
import com.zmn.oms.dubbo.dto.zmn.serviceitem.OrderServiceItemDRO;
import com.zmn.oms.dubbo.impl.zmn.order.OrderWorkBaseRemoteService;
import com.zmn.oms.dubbo.interfaces.zmn.normal.order.ZsNormalOrderWorkRemoteService;
import com.zmn.oms.dubbo.utils.DubboConsts;
import com.zmn.oms.model.bo.work.apply.cancel.CancelApplyResultBO;
import com.zmn.oms.model.dto.order.zmn.ZsNormalNewOrderDTO;
import com.zmn.oms.model.dto.order.zmn.ZsNormalUpdateOrderDTO;
import com.zmn.oms.model.dto.work.masterwork.ModifyDutyTimeDTO;
import com.zmn.oms.model.entity.changerecord.OrderChangeRecord;
import com.zmn.oms.model.entity.comment.OrderComment;
import com.zmn.oms.model.entity.detail.OrderDetail;
import com.zmn.oms.model.entity.discount.OrderDiscount;
import com.zmn.oms.model.entity.log.OrderLog;
import com.zmn.oms.model.entity.omstrack.OrderWorkTrack;
import com.zmn.oms.model.entity.product.OrderProduct;
import com.zmn.oms.model.entity.serviceitem.OrderServiceItem;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.entity.work.OrderWorkQuery;
import com.zmn.oms.model.entity.work.list.OrderWorkOuterQuery;
import com.zmn.base.oms.common.model.es.orderwork.EsOrderWork;
import com.zmn.oms.model.vo.warranty.WarrantyListOrderVO;
import com.zmn.oms.model.vo.work.modify.amount.ZsServiceItemVO;
import com.zmn.oms.services.interfaces.changerecord.OrderChangeRecordService;
import com.zmn.oms.services.interfaces.comment.OrderCommentService;
import com.zmn.oms.services.interfaces.orderencrypt.OrderEncryptService;
import com.zmn.oms.services.interfaces.product.OrderProductService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.services.interfaces.worktrack.WorkTrackService;
import com.zmn.oms.zmn.business.interfaces.discount.ZsOrderDiscountBService;
import com.zmn.oms.zmn.business.interfaces.work.ZsOrderWorkBService;
import com.zmn.oms.zmn.business.interfaces.work.ZsOrderWorkOperatePermissionBService;
import com.zmn.oms.zmn.normal.business.interfaces.order.ZsNormalOrderBService;
import com.zmn.oms.zmn.normal.business.interfaces.work.ZsNormalWorkBService;
import com.zmn.pay.common.constant.PayConsts;
import com.zmn.saas.dubbo.constant.SaasDubboConsts;
import com.zmn.saas.dubbo.dto.shop.ShopDIO;
import com.zmn.saas.dubbo.dto.shop.ShopDRO;
import com.zmn.saas.dubbo.interfaces.shop.ShopRemoteService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedLongTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.stream.Collectors;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;

/**
 * 类描述：订单 remote service
 *
 * @author liuying
 * @date 2018/11/07 15:10
 */
@Service(loadbalance = "roundrobin", timeout = 20000, retries = 2, version = DubboConsts.INTERFACE_VERSION, validation = "false")
public class ZsNormalOrderWorkRemoteServiceImpl extends OrderWorkBaseRemoteService implements ZsNormalOrderWorkRemoteService {

    static final String TAG = "啄木鸟-普通单";
    @Autowired
    OrderWorkListBService orderWorkListBService;
    @Autowired
    OrderCommentService orderCommentService;
    @Autowired
    OrderWorkService orderWorkService;
    @Autowired
    OrderProductService orderProductService;
    @Autowired
    OrderLogBService orderLogBService;
    @Autowired
    ZsNormalWorkBService zsNormalWorkBService;
    @Autowired
    ZsNormalOrderBService zsNormalOrderBService;
    @Autowired
    ZsOrderDiscountBService zsOrderDiscountBService;
    @Autowired
    OrderChangeRecordService orderChangeRecordService;
    @Autowired
    OrderWarrantyBService orderWarrantyBService;
    @Autowired
    OrderDiscountCalcBService orderDiscountCalcBService;
    @Autowired
    ZsOrderWorkBService zsOrderWorkBService;
    @Autowired
    WorkTrackService workTrackService;
    @Autowired
    WorkTrackBService workTrackBService;
    @Autowired
    ZsOrderWorkOperatePermissionBService zsOrderWorkOperatePermissionBService;
    @Autowired
    OrderEncryptService orderEncryptService;
    @Autowired
    OrderWorkEsBService orderWorkEsBService;
    @Autowired
    CancelApplyBService cancelApplyBService;

    @Reference(version = SaasDubboConsts.INTERFACE_VERSION, check = false)
    ShopRemoteService shopRemoteService;
    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    protected PilotRemoteService pilotRemoteService;

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public ResponseDTO<OrderDRO> getOrderWorkByOuterId(@NotNull String outerId) {

        logger.info("#oms#通过第三方订单id查询 {}", outerId);

        OrderWorkOuterQuery query = new OrderWorkOuterQuery();
        query.setOuterId(outerId);
        List<EsOrderWork> esOrderWorkList = orderWorkListBService.listPageOrderWorkByQuery(query);
        // 解密电话和地址
        orderEncryptService.batchDecryptEsOrderWork(esOrderWorkList, EncryptFieldTypeEnum.USER_TELPHONE, EncryptFieldTypeEnum.USER_ADDRESS);

        if (esOrderWorkList.isEmpty()) {
            return com.zmn.common.dto2.ResponseDTO.fail("订单不存在");
        }
        OrderDRO orderDRO = this.getOrderDRO(esOrderWorkList.get(0));
        return com.zmn.common.dto2.ResponseDTO.success(orderDRO);
    }

    /**
     * 获取订单信息
     *
     * @param workId
     * @return
     */
    @Override
    public ResponseDTO<OrderDRO> getOrderByWorkId(@NotNull Long workId) {
        logger.info("获取订单信息入参workId={}", workId);

        OrderWorkQuery query = new OrderWorkQuery();
        query.setCode(workId);
        List<EsOrderWork> esOrderWorkList = orderWorkListBService.listPageOrderWorkByQuery(query);
        if (esOrderWorkList.isEmpty()) {
            return ResponseDTO.fail("订单不存在");
        }
        // 解密电话和地址
        orderEncryptService.batchDecryptEsOrderWork(esOrderWorkList, EncryptFieldTypeEnum.USER_TELPHONE, EncryptFieldTypeEnum.USER_ADDRESS);
        OrderDRO orderDRO = this.getOrderDRO(esOrderWorkList.get(0));
        return ResponseDTO.success(orderDRO, DubboConsts.OK);
    }

    @Override
    public ResponseDTO<List<OrderDRO>> listOrderByWorkIds(@NotNull List<Long> workIds) {
        logger.info("获取订单信息入参workIds={}", JSON.toJSONString(workIds));

        OrderWorkQuery query = new OrderWorkQuery();
        query.setOrderIdList(workIds);
        query.setPageSize(10000);
        query.setIncludes(Lists.newArrayList("id", "type", "contact.phone", "contact.phoneEnd4", "servCategId", "categOneId", "categTwoId", "bizType", "bizLine", "servProductGroupId", "servProductGroupName", "showCategTwoName", "showCategOneName", "companyId", "manageCompanyId", "provinceId", "cityId", "cityName", "countyId", "channelOneId", "channelTwoId", "channelId", "channelName", "orderTagList", "receiveTime", "resultStatus", "isQuotationValid", "servItemType", "completeTime", "masterId", "masterName", "distributeTime", "takeTime"));
        List<EsOrderWork> esOrderWorkList = orderWorkListBService.listPageOrderWorkByQuery(query);

        if (esOrderWorkList.isEmpty()) {
            return ResponseDTO.fail("订单不存在");
        }
        // 解密电话
        orderEncryptService.batchDecryptEsOrderWork(esOrderWorkList, EncryptFieldTypeEnum.USER_TELPHONE);

        List<OrderDRO> orderDROs = Lists.newArrayList();
        esOrderWorkList.forEach(esOrderWork -> {
            OrderDRO orderDRO = new OrderDRO();

            orderDRO.setWorkId(esOrderWork.getId());
            orderDRO.setType(esOrderWork.getType());
            orderDRO.setPhone(esOrderWork.getContact().getPhone());
            orderDRO.setPhoneEnd4(esOrderWork.getContact().getPhoneEnd4());
            orderDRO.setServCategId(esOrderWork.getServCategId());
            orderDRO.setBizType(esOrderWork.getBizType());
            orderDRO.setBizLine(esOrderWork.getBizLine());
            orderDRO.setServProductGroupId(esOrderWork.getServProductGroupId());
            orderDRO.setServProductGroupName(esOrderWork.getServProductGroupName());
            orderDRO.setShowCategName(esOrderWork.getShowCategTwoName());
            orderDRO.setShowCategOneName(esOrderWork.getShowCategOneName());
            orderDRO.setCategId(esOrderWork.getCategTwoId());
            orderDRO.setCategOneId(esOrderWork.getCategOneId());
            orderDRO.setCompanyId(esOrderWork.getCompanyId());
            orderDRO.setManageCompanyId(esOrderWork.getManageCompanyId());
            orderDRO.setManageCompanyame(esOrderWork.getManageCompanyName());
            orderDRO.setGridCompanyId(esOrderWork.getGridCompanyId());
            orderDRO.setGridCompanyName(esOrderWork.getGridCompanyName());
            orderDRO.setGridManageCompanyId(esOrderWork.getGridManageCompanyId());
            orderDRO.setGridManageCompanyName(esOrderWork.getGridManageCompanyName());
            orderDRO.setProvinceId(esOrderWork.getProvinceId());
            orderDRO.setCityId(esOrderWork.getCityId());
            orderDRO.setCityName(esOrderWork.getCityName());
            orderDRO.setCountryId(esOrderWork.getCountyId());
            orderDRO.setChannelOneId(esOrderWork.getChannelOneId());
            orderDRO.setChannelTwoId(esOrderWork.getChannelTwoId());
            orderDRO.setChannelId(esOrderWork.getChannelId());
            orderDRO.setChannelName(esOrderWork.getChannelName());
            List<OrderTagDRO> orderTagList = BeanMapper.mapList(esOrderWork.getOrderTagList(), OrderTagDRO.class);
            orderDRO.setOrderTagList(orderTagList);
            orderDRO.setCreateTime(esOrderWork.getReceiveTime());
            orderDRO.setResultStatus(esOrderWork.getResultStatus());
            orderDRO.setServItemType(esOrderWork.getServItemType());
            orderDRO.setIsQuotationValid(esOrderWork.getIsQuotationValid());
            orderDRO.setCompleteTime(esOrderWork.getCompleteTime());
            orderDRO.setMasterId(esOrderWork.getMasterId());
            orderDRO.setMasterName(esOrderWork.getMasterName());
            orderDRO.setDistributeTime(esOrderWork.getDistributeTime());
            orderDRO.setTakeTime(esOrderWork.getTakeTime());
            orderDROs.add(orderDRO);
        });

        return ResponseDTO.success(orderDROs, DubboConsts.OK);
    }

    @Override
    public ResponseDTO<Integer> getCouponDiscountAmountByOrderIdList(List<Long> orderIdList) {
        Integer couponDiscountAmount = orderWorkListBService.getCouponDiscountAmountByOrderIdList(orderIdList);
        return ResponseDTO.success(couponDiscountAmount, DubboConsts.OK);
    }

    @Override
    public ResponseDTO<OrderDRO> getOrderByWarrantyCode(String warrantyCode) {
        try {
            OrderWorkQuery query = new OrderWorkQuery();
            query.setWarrantyCode(warrantyCode);

            List<EsOrderWork> esOrderWorkList = orderWorkListBService.listPageOrderWorkByQuery(query);
            if (esOrderWorkList.isEmpty()) {
                return ResponseDTO.fail("订单不存在");
            }

            // 解密电话和地址
            orderEncryptService.batchDecryptEsOrderWork(esOrderWorkList, EncryptFieldTypeEnum.USER_TELPHONE, EncryptFieldTypeEnum.USER_ADDRESS);
            OrderDRO orderDRO = this.getOrderDRO(esOrderWorkList.get(0));
            return ResponseDTO.success(orderDRO, DubboConsts.OK);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("[{}] 获取订单错误：{}", TAG, e);
            return ResponseDTO.fail(e.getMessage());
        }
    }

    @Override
    public ResponseDTO<WeixinOrderDetailDRO> getWeixinOrderDetailById(Long orderId, Long workId) {

        OrderWork dbOrderWork = orderWorkService.findOrderWorkByKey(orderId, workId);
        if (dbOrderWork == null) {
            return ResponseDTO.fail("not find order!");
        }

        WeixinOrderDetailDRO weixinOrderDetail = getWeixinOrderDetailDRO(dbOrderWork);

        // 存在退款单
        if (NumberUtil.isNotNullOrZero(dbOrderWork.getRefundTargetWorkId())) {
            // 原单退款单 进行补全数据
            OrderWorkQuery query = new OrderWorkQuery();
            query.setOrderId(orderId);
            query.setWorkType(Arrays.asList(OrderConsts.ORDER_TYPE_REFUND));
            query.setOrderField("receiveTime");
            List<EsOrderWork> esOrderWorkList = orderWorkListBService.listPageOrderWorkByQuery(query);
            if (CollectionUtil.isNotNullOrEmpty(esOrderWorkList)) {
                EsOrderWork esOrderWork = esOrderWorkList.get(0);
                Integer refundAmount = esOrderWorkList.stream().filter(e -> e.getRefundAmount() != null).mapToInt(e -> e.getRefundAmount()).sum();
                weixinOrderDetail.setRefundTime(esOrderWork.getLastRefundAmountTime());
                weixinOrderDetail.setRefundAmount(refundAmount);
                weixinOrderDetail.setRefundStatus(esOrderWork.getPayStatus());
                weixinOrderDetail.setCompleteRefundStatus(GlobalConsts.YES);
                weixinOrderDetail.setRefundOrderCount(esOrderWorkList.size());
                weixinOrderDetail.setLastRefundAmount(esOrderWork.getRefundAmount());
            }else {
                weixinOrderDetail.setRefundOrderCount(GlobalConsts.NONE);
            }
        }

        logger.debug("订单详情DRO[{}]", weixinOrderDetail);
        return ResponseDTO.success(weixinOrderDetail);
    }

    @Override
    public ResponseDTO<List<OrderLogDRO>> listOrderLogsById(@NotNull Long workId, @NotNull Long orderId) {

        List<OrderLogDRO> logsDro = Lists.newArrayList();
        List<OrderLog> orderLogsByTypes = orderLogBService.findOrderLogsByWorkId(workId);

        if (CollectionUtils.isEmpty(orderLogsByTypes)) {
            return ResponseDTO.success(logsDro);
        }

        logsDro = BeanMapper.mapList(orderLogsByTypes, OrderLogDRO.class);

        return ResponseDTO.success(logsDro);
    }

    @Override
    public ResponseDTO cancelOrder(CancelOrderDIO cancelOrderDIO) {
        logger.info("[{}] 取消订单：{}", TAG, cancelOrderDIO);

        ValidateResult validateResult = ValidatorUtil.validator(cancelOrderDIO);
        if (!validateResult.isSuccess()) {
            logger.error("[{}] 参数错误：{}", TAG, validateResult.toString());
            return ResponseDTO.fail("提交参数错误");
        }

        cancelOrderDIO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_USER);
        return super.cancelOrder(cancelOrderDIO);
    }

    @Override
    public ResponseDTO<NewOrderDRO> updateOrder(UpdateOrderDIO updateOrderDIO) {
        logger.info("[{}] 修改订单：{}", TAG, updateOrderDIO);

        ValidateResult validateResult = ValidatorUtil.validator(updateOrderDIO);
        if (!validateResult.isSuccess()) {
            logger.error("[{}] 参数错误：{}", TAG, validateResult.toString());
            return ResponseDTO.fail("提交参数错误：" + validateResult.toString());
        }

        // DIO转换
        ZsNormalUpdateOrderDTO normalNewOrderDTO = BeanMapper.map(updateOrderDIO, ZsNormalUpdateOrderDTO.class);

        return super.updateOrder(normalNewOrderDTO);
    }

    @Override
    public ResponseDTO<Boolean> updateFinalPriceOrderToAfterPay(Long orderId) {
        logger.info("[{}] 修改为后付：{}", TAG, orderId);

        boolean flag = orderWorkBService.updateFinalPriceOrderToAfterPay(orderId);
        return ResponseDTO.success(flag);
    }

    @Override
    public ResponseDTO<NewOrderDRO> insertOrder(NewOrderDIO newOrderDIO) {
        logger.info("[{}] 添加订单：{}", TAG, JSON.toJSONString(newOrderDIO));

        ValidateResult validateResult = ValidatorUtil.validator(newOrderDIO);
        if (!validateResult.isSuccess()) {
            logger.error("[{}] 参数错误：{}", TAG, validateResult.toString());
            return ResponseDTO.fail("提交参数错误：" + validateResult.toString());
        }
        if (StringUtils.isBlank(newOrderDIO.getOperator())) {
            newOrderDIO.setOperator("系统");
        }

        // DIO转换
        ZsNormalNewOrderDTO normalNewOrderDTO = BeanMapper.map(newOrderDIO, ZsNormalNewOrderDTO.class);
        normalNewOrderDTO.setReceiverManner(OrderConsts.RECEIVE_MANNER_MANUAL);
        normalNewOrderDTO.setAutoDistribute(newOrderDIO.getDutyMasterId());
        logger.info("未替换下单接口：[com.zmn.oms.dubbo.impl.zmn.normal.order.ZsNormalOrderWorkRemoteServiceImpl.insertOrder]，下单渠道：[{}]，下单方式：[{}]", normalNewOrderDTO.getChannelId(), normalNewOrderDTO.getReceiveEntranceId());
        return super.addOrder(normalNewOrderDTO);
    }

    @Override
    public ResponseDTO<List<SimpleOrderDRO>> getMyOrderListByUserId(Long userId) {
        OrderWorkQuery query = new OrderWorkQuery();
        query.setUserId(userId);
        query.setPageSize(1000);
        query.setPageIndex(1);
        query.setOrderField("receiveTime");
        query.setWorkType(Lists.newArrayList(OrderConsts.ORDER_TYPE_REWORK, OrderConsts.ORDER_TYPE_NEW));
        List<EsOrderWork> esOrderWorkList = orderWorkListBService.listPageOrderWorkByQuery(query);
        // 解密电话和地址
        orderEncryptService.batchDecryptEsOrderWork(esOrderWorkList, EncryptFieldTypeEnum.USER_TELPHONE, EncryptFieldTypeEnum.USER_ADDRESS);
        List<SimpleOrderDRO> orderDROList = Lists.newLinkedList();

        if (CollectionUtils.isEmpty(esOrderWorkList)) {
            return ResponseDTO.success(orderDROList);
        }
        orderDROList = this.processOrderListToSimpleList(esOrderWorkList);

        return ResponseDTO.success(orderDROList);
    }

    @Override
    public ResponseDTO<UserOrderPageDRO> listPageOrderByUserId(UserOrderQueryDIO query) {

        ValidateResult validateResult = ValidatorUtil.validator(query);
        if (!validateResult.isSuccess()) {
            logger.error("listPageOrderByUserId 参数错误：{}", validateResult.toString());
            return ResponseDTO.fail(validateResult.getErrMsg()[0]);
        }

        OrderWorkQuery orderWorkQuery = new OrderWorkQuery();
        orderWorkQuery.setUserId(query.getUserId());
        orderWorkQuery.setPageSize(query.getPageSize());
        orderWorkQuery.setPageIndex(query.getPageIndex());
        orderWorkQuery.setOrderField("receiveTime");
        orderWorkQuery.setWorkType(Lists.newArrayList(OrderConsts.ORDER_TYPE_REWORK, OrderConsts.ORDER_TYPE_NEW));
        List<EsOrderWork> esOrderWorkList = orderWorkListBService.listPageOrderWorkByQuery(orderWorkQuery);
        List<SimpleOrderDRO> orderDROList = Lists.newLinkedList();
        UserOrderPageDRO pageDRO = new UserOrderPageDRO();
        pageDRO.setTotalCount(orderWorkQuery.getTotalCount());
        pageDRO.setOrderList(orderDROList);

        if (CollectionUtils.isEmpty(esOrderWorkList)) {
            return com.zmn.common.dto2.ResponseDTO.success(pageDRO);
        }
        // 解密电话和地址
        orderEncryptService.batchDecryptEsOrderWork(esOrderWorkList, EncryptFieldTypeEnum.USER_TELPHONE, EncryptFieldTypeEnum.USER_ADDRESS);

        List<SimpleOrderDRO> list = this.processOrderListToSimpleList(esOrderWorkList);
        pageDRO.setOrderList(list);
        return ResponseDTO.success(pageDRO);
    }

    /**
     * 根据自定义tab条件和多用户查询工单列表
     * 1.待接单：2.待上门：3.待评价：4.已取消：5.已完成且存在且发放保修卡：6.已发起返修
     * @param queryDIO
     * @return
     */
    @Override
    public ResponseDTO<List<OrderListAppDRO>> listPageOrderByTabTypeQuery(OrderTabTypeQueryDIO queryDIO) {
        logger.info("#oms#listPageOrderByTabTypeQuery 根据自定义tab条件和多用户查询工单列表入参:{}", JSON.toJSONString(queryDIO));

        OrderWorkQuery query = new OrderWorkQuery();
        query.setPageSize(queryDIO.getPageSize());
        query.setPageIndex(Optional.ofNullable(queryDIO.getPageIndex()).orElse(1));
        query.setOrderField("receiveTime");
        query.setUserIdList(queryDIO.getUserIdList());
        query.setPlatWork(queryDIO.getPlat());
        query.setWorkType(Lists.newArrayList(OrderConsts.ORDER_TYPE_REWORK, OrderConsts.ORDER_TYPE_NEW));
        // 不查询未成单数据
        query.setNonTagId(OrderTagConsts.TAG_ID_UN_AVAILABLE_SERVICE);
        if (CollectionUtils.isNotEmpty(queryDIO.getOrderIdList())) {
            query.setOrderIdList(queryDIO.getOrderIdList());
        }

        Integer tabType = queryDIO.getTabType();
        if (tabType != null) {
            switch (tabType) {
                case OrderConsts.QUERY_TAB_ONE:
                    // 待领单 （已录入，已确认，已派单-进行中）
                    query.setWorkStatus(Lists.newArrayList(
                            OrderStatusConsts.WORK_STATUS_INPUT,
                            OrderStatusConsts.WORK_STATUS_CONFIRM,
                            OrderStatusConsts.WORK_STATUS_ASSIGN,
                            OrderStatusConsts.WORK_STATUS_DISTRIBUTE
                    ));
                    query.setWorkResultStatus(OrderStatusConsts.WORK_RESULT_DOING);
                    query.setNotWaitCancel(GlobalConsts.YES);
                    break;
                case OrderConsts.QUERY_TAB_TWO:
                    // 待领单上门 （已领单-进行中）
                    query.setWorkStatus(Lists.newArrayList(OrderStatusConsts.WORK_STATUS_TAKE));
                    query.setWorkResultStatus(OrderStatusConsts.WORK_RESULT_DOING);
                    query.setNotWaitCancel(GlobalConsts.YES);
                    break;
                case OrderConsts.QUERY_TAB_THREE:
                    // 待评价
                    query.setExistCompleteTime(GlobalConsts.YES);
                    query.setExistCommentTime(GlobalConsts.NO);
                    query.setNotWaitCancel(GlobalConsts.YES);
                    break;
                case OrderConsts.QUERY_TAB_FOUR:
                    // 已取消（弃单/失败）
                    query.setWorkResultStatusList(Lists.newArrayList(OrderStatusConsts.WORK_RESULT_FAIL, OrderStatusConsts.WORK_RESULT_DISCARD));
                    query.setExistCompleteTime(GlobalConsts.NO);
                    break;
                case OrderConsts.QUERY_TAB_FIVE:
                    // 已完成且存在且发放保修卡
                    query.setExistCompleteTime(GlobalConsts.YES);
                    query.setHasWarrantyCode(GlobalConsts.YES);
                    query.setNotWaitCancel(GlobalConsts.YES);
                    break;
                case OrderConsts.QUERY_TAB_SIX:
                    // 已返修
                    query.setWorkType(Lists.newArrayList(OrderConsts.ORDER_TYPE_REWORK));
                    query.setNotWaitCancel(GlobalConsts.YES);
                    break;
                default:
                    // 不处理
                    break;
            }
        }

        List<EsOrderWork> esOrderWorkList = orderWorkListBService.listPageOrderWorkByQuery(query);

        List<OrderListAppDRO> orderDROList = Lists.newLinkedList();
        if (CollectionUtils.isEmpty(esOrderWorkList)) {
            return ResponseDTO.success(orderDROList);
        }

        // 订单转换
        List<SimpleOrderDRO> orderSimpleList = this.processOrderListToSimpleList(esOrderWorkList);
        orderDROList = BeanMapper.mapList(orderSimpleList, OrderListAppDRO.class);

        if (Objects.equals(tabType, OrderConsts.QUERY_TAB_ONE)) {
            // 待接单过滤待支付订单
            orderDROList = orderDROList.stream().filter(e -> !Objects.equals(e.getPrepayStatus(), PayConsts.PAY_STATUS_ING)).collect(Collectors.toList());
        } else if (Objects.equals(tabType, OrderConsts.QUERY_TAB_FIVE)) {
            // 保修未过期
            // 查询订单保修信息
            Set<Long> orderIdCollect = esOrderWorkList.stream().map(EsOrderWork::getOrderId).collect(Collectors.toSet());
            List<WarrantyListOrderVO> warrantyList = orderWarrantyBService.listWarrantyByOrderIdList(Lists.newArrayList(orderIdCollect));
            Map<Long, WarrantyListOrderVO> orderWarranty = warrantyList.stream().collect(Collectors.toMap(WarrantyListOrderVO::getOrderId, obj -> obj));

            // 组装保修卡信息
            orderDROList.forEach((item) -> {
                WarrantyListOrderVO warrantyOrder = orderWarranty.get(item.getOrderId());
                if (Objects.nonNull(warrantyOrder)) {
                    item.setEffectiveTime(warrantyOrder.getEffectiveTime());
                    item.setExpiredTime(warrantyOrder.getExpiredTime());
                    item.setEffectived(warrantyOrder.getEffectived());
                    item.setWarrantyType(warrantyOrder.getType());
                }
            });
            // 过滤只是保修卡的数据
            orderDROList = orderDROList.stream().filter(e -> Objects.equals(OrderConsts.ORDER_WARRANTY_TYPE_CARD, e.getWarrantyType()) && e.getExpiredTime() != null).collect(Collectors.toList());
        }

        return ResponseDTO.success(orderDROList);
    }

    /**
     * 修改预约时间
     *
     * @param trackModifyDutyTimeDIO
     * @return com.zmn.common.dto2.ResponseDTO
     * @author wangxiaokun
     */
    @Override
    public ResponseDTO modifyDutyTime(TrackModifyDutyTimeDIO trackModifyDutyTimeDIO) {
        try {
            logger.info("修改预约时间入参:[{}]", JSON.toJSONString(trackModifyDutyTimeDIO));
            ModifyDutyTimeDTO dto = BeanMapper.map(trackModifyDutyTimeDIO, ModifyDutyTimeDTO.class);
            zsOrderWorkBService.modifyDutyTime(dto);
            return ResponseDTO.success();
        } catch (OmsBaseException omsBaseException) {
            omsBaseException.printStackTrace();
            return ResponseDTO.fail(omsBaseException.getMessage());
        }
    }

    /**
     * 查询多用户的所有订单 （品牌站使用）
     *
     * @param userListOrderQueryDIO
     * @return
     */
    @Override
    public ResponseDTO<List<SimpleOrderDRO>> getOrderListByUserIdList(UserListOrderQueryDIO userListOrderQueryDIO){

        List<SimpleOrderDRO> orderDROList = Lists.newLinkedList();

        NativeSearchQuery build = new NativeSearchQueryBuilder()
                .withPageable(PageRequest.of(userListOrderQueryDIO.getPageIndex(), userListOrderQueryDIO.getPageSize()))
                .withSort(SortBuilders.fieldSort("receiveTime").order(SortOrder.DESC))
                .withQuery(boolQuery()
                        .filter(QueryBuilders.termQuery("plat", userListOrderQueryDIO.getPlat()))
                        .filter(QueryBuilders.termsQuery("type", Arrays.asList(OrderConsts.ORDER_TYPE_NEW, OrderConsts.ORDER_TYPE_REWORK)))
                        .filter(boolQuery()
                                .must(QueryBuilders.termsQuery("type", userListOrderQueryDIO.getStatusList()))
                                .must(QueryBuilders.termsQuery("userId", userListOrderQueryDIO.getUserIdList()))
                        ))
                .build();
        List<EsOrderWork> esOrderWorkList = orderWorkEsBService.listPageByQuery(build);

        if (CollectionUtils.isEmpty(esOrderWorkList)) {
            return ResponseDTO.success(orderDROList);
        }

        orderDROList = this.processOrderListToSimpleList(esOrderWorkList);
        return ResponseDTO.success(orderDROList);
    }

    /**
     * 查询多用户的所有订单
     *
     * @param userIdList
     * @return
     */
    @Override
    public ResponseDTO<List<SimpleOrderDRO>> getMyOrderListByUserIdList(List<Long> userIdList){
        logger.info("查询多用户的所有订单#getMyOrderListByUserIdList userIdList={}", userIdList);
        List<SimpleOrderDRO> orderDROList = Lists.newLinkedList();

        NativeSearchQuery build = new NativeSearchQueryBuilder()
                .withPageable(PageRequest.of(0, 1000))
                .withSort(SortBuilders.fieldSort("receiveTime").order(SortOrder.DESC))
                .withQuery(boolQuery()
                        .filter(boolQuery()
                                .must(QueryBuilders.termsQuery("type", Lists.newArrayList(OrderConsts.ORDER_TYPE_REWORK, OrderConsts.ORDER_TYPE_NEW)))
                                .must(QueryBuilders.termsQuery("userId", userIdList))
                        ))
                .build();
        List<EsOrderWork> esOrderWorkList = orderWorkEsBService.listPageByQuery(build);

        if (CollectionUtils.isEmpty(esOrderWorkList)) {
            return ResponseDTO.success(orderDROList);
        }

        orderDROList = this.processOrderListToSimpleList(esOrderWorkList);
        return ResponseDTO.success(orderDROList);
    }


    @Override
    public ResponseDTO<UsersOrderDoingDRO> haveOrdersDoingByUserIdList(Set<Long> userIdList) {
        logger.info("haveOrdersDoingByUserIdList 收到请求 userIdList[{}]", userIdList);
        if (userIdList == null) {
            return ResponseDTO.fail("用户Id不能为空");
        }

        UsersOrderDoingDRO usersOrderDoing = new UsersOrderDoingDRO();
        // 用户关联订单 是否存在 未完成，进行中订单
        OrderWorkQuery query = new OrderWorkQuery();
        query.setUserIdList(Lists.newArrayList(userIdList));
        query.setWorkType(Lists.newArrayList(OrderConsts.ORDER_TYPE_REWORK, OrderConsts.ORDER_TYPE_NEW));
        query.setWorkResultStatus(OrderStatusConsts.WORK_RESULT_DOING);
        query.setExistCompleteTime(GlobalConsts.NO);
        Integer orderListCount = orderWorkListBService.countOrderWorkByQuery(query);
        usersOrderDoing.setDoingOrder(orderListCount > 0);

        // 处理保修时间 最大保修 < now()
        String startTime = DateUtil.getNowFormatted();
        Date endTimeDate = DateUtil.addMonth(new Date(), 18);
        String endTime = DateUtil.toString(endTimeDate, "yyyy-MM-dd 23:59:59");

        // 下单用户关联订单的保修卡 是否存在未过期的保修卡
        OrderWorkQuery warrantyQuery = new OrderWorkQuery();
        warrantyQuery.setUserIdList(Lists.newArrayList(userIdList));
        warrantyQuery.setWorkType(Lists.newArrayList(OrderConsts.ORDER_TYPE_REWORK, OrderConsts.ORDER_TYPE_NEW));
        warrantyQuery.setExistCompleteTime(GlobalConsts.YES);
        warrantyQuery.setWarrantyProductMaxExpiredTime(startTime + "," + endTime);
        Integer orderListWarrantyCount = orderWorkListBService.countOrderWorkByQuery(warrantyQuery);

        // 扫码用户关联订单的保修卡 是否存在未过期的保修卡
        OrderWorkQuery countQuery = new OrderWorkQuery();
        countQuery.setVisitUserIdList(Lists.newArrayList(userIdList));
        countQuery.setWorkType(Lists.newArrayList(OrderConsts.ORDER_TYPE_REWORK, OrderConsts.ORDER_TYPE_NEW));
        countQuery.setExistCompleteTime(GlobalConsts.YES);
        countQuery.setWarrantyProductMaxExpiredTime(startTime + "," + endTime);
        List<EsOrderWork> orderListVisitWarrantyCount = orderWorkListBService.listPageOrderWorkByQuery(countQuery);

        usersOrderDoing.setExistEffectiveWarranty(orderListWarrantyCount > 0 || orderListVisitWarrantyCount.size() > 0);
        logger.info("userIdList=【{}】，haveOrdersDoingByUserIdList 数量 doingOrder={}，userWarranty={}，visitWarranty={}", userIdList, orderListCount, orderListWarrantyCount, orderListVisitWarrantyCount.size());
        return ResponseDTO.success(usersOrderDoing);
    }

    private List<SimpleOrderDRO> processOrderListToSimpleList(List<EsOrderWork> esOrderWorkList){

        List<SimpleOrderDRO> orderDROList = Lists.newLinkedList();
        List<Long> orderIdList = esOrderWorkList.stream().map(EsOrderWork::getOrderId).collect(Collectors.toList());
        List<OrderWork> orderWorkList = orderWorkService.listEsOrderWorkByOrderIdList(orderIdList);
        // 解密电话和地址
        orderEncryptService.batchDecryptEsOrderWork(esOrderWorkList, EncryptFieldTypeEnum.USER_TELPHONE, EncryptFieldTypeEnum.USER_ADDRESS);

        Map<Long, OrderWork> orderWorkMap = orderWorkList.stream().collect(Collectors.toMap(OrderWork::getWorkId, e -> e));
        List<OrderComment> orderComments = orderCommentService.listOrderCommentByOrderIdList(orderIdList);
        Map<Long, OrderComment> orderCommentMap = orderComments.stream().collect(Collectors.toMap(OrderComment::getCommentId, orderComment -> orderComment));

        esOrderWorkList.forEach(item -> {
            SimpleOrderDRO simpleOrderDRO = this.getSimpleOrderDRO(item);
            OrderWork orderWork = orderWorkMap.get(item.getId());
            if (orderWork == null) {
                return;
            }
            simpleOrderDRO.setFinalPrice(orderWork.getFinalPrice());
            simpleOrderDRO.setReceiveTime(orderWork.getReceiveTime());
            simpleOrderDRO.setPrepayStatus(orderWork.getPrepayStatus());
            simpleOrderDRO.setRefundStatus(OrderConsts.getUserRefundStatus(NumberUtil.isNotNullOrZero(orderWork.getRefundTargetWorkId()), orderWork.getRefundReviewStatus(), orderWork.getPayStatus()));
            simpleOrderDRO.setOriginalAmount(orderWork.getOriginalAmount());
            simpleOrderDRO.setTotalAmount(this.getTotalAmount(orderWork));
            simpleOrderDRO.setFactAmount(this.factAmount(orderWork));
            OrderCommentDRO orderCommentDRO = processOrderCommentDro(orderCommentMap.get(orderWork.getOrderId()));
            simpleOrderDRO.setIsComment(Objects.nonNull(orderCommentDRO));
            simpleOrderDRO.setComment(orderCommentDRO);
            orderDROList.add(simpleOrderDRO);
        });

        return orderDROList;
    }


    @Override
    public ResponseDTO<OrderCountDRO> getOrderCountByProductId(Integer productId, Date month) {
        if (productId == null) {
            return ResponseDTO.fail("提交参数错误：产品id不能为空。");
        }
        if (month == null) {
            // 如果没提供月份，默认查当月
            month = DateUtil.getNow();
        }
        String monthFirstDay = DateUtil.getMonthFirstDay(month);
        String monthLastDay = DateUtil.getMonthLastDay(month);

        OrderWorkQuery query = new OrderWorkQuery();
        query.setProductId(productId);
        query.setReceiveTime(monthFirstDay + "," + monthLastDay);
        // 只查微信渠道
        query.setChannelIdList(Lists.newArrayList(GlobalConsts.CHANNEL_WEIXIN_ID));
        query.setWorkType(Arrays.asList(OrderConsts.ORDER_TYPE_NEW, OrderConsts.ORDER_TYPE_REWORK));

        Integer orderCount = orderWorkListBService.countOrderWorkByQuery(query);
        logger.debug("[{}]后端产品查询销量数据[{}]", query, orderCount);
        OrderCountDRO orderCountDRO = new OrderCountDRO();
        orderCountDRO.setMonthOrderCount(orderCount);

        return ResponseDTO.success(orderCountDRO);
    }

    @Override
    public ResponseDTO<OrderCountDRO> getOrderCountByShowProductId(Integer showProductId, Date month) {
        if (showProductId == null) {
            return ResponseDTO.fail("提交参数错误：前台产品id不能为空。");
        }
        if (month == null) {
            // 如果没提供月份，默认查当月
            month = DateUtil.getNow();
        }
        String monthFirstDay = DateUtil.getMonthFirstDay(month);
        String monthLastDay = DateUtil.getMonthLastDay(month);

        OrderWorkQuery query = new OrderWorkQuery();
        query.setShowProductId(showProductId);
        query.setReceiveTime(monthFirstDay + "," + monthLastDay);
        // 只查微信渠道
        query.setChannelIdList(Lists.newArrayList(GlobalConsts.CHANNEL_WEIXIN_ID));
        query.setWorkType(Arrays.asList(OrderConsts.ORDER_TYPE_NEW, OrderConsts.ORDER_TYPE_REWORK));

        Integer orderCount = orderWorkListBService.countOrderWorkByQuery(query);
        logger.debug("[{}]前端产品查询销量数据[{}]", query, orderCount);
        OrderCountDRO orderCountDRO = new OrderCountDRO();
        orderCountDRO.setMonthOrderCount(orderCount);

        return ResponseDTO.success(orderCountDRO);
    }

    @Override
    public ResponseDTO<OrderCountDRO> getOrderCountByShowProductIdAndShopId(Integer productId, Date month, Integer shopId) {
        logger.debug("getOrderCountByShowProductIdAndShopId 收到请求 shopId[{}]", shopId);
        if (productId == null) {
            return ResponseDTO.fail("提交参数错误：产品id不能为空。");
        }

        ShopDIO shopDIO = new ShopDIO();
        shopDIO.setShopId(shopId);
        com.zmn.common.dto.ResponseDTO<ShopDRO> shopResponse = shopRemoteService.getShop(shopDIO);
        logger.debug("getShop 获取店铺信息出参[{}]", shopResponse);
        if (!shopResponse.getStatusBool()) {
            return ResponseDTO.fail("店铺获取失败，未查询到对应的店铺id[" + shopId + "]的相关信息");
        }
        ShopDRO shopDRO = shopResponse.getData();

        OrderWorkQuery query = new OrderWorkQuery();
        if (!Objects.isNull(month)) {
            // 如果没提供月份，默认查当月
            String monthFirstDay = DateUtil.getMonthFirstDay(month);
            String monthLastDay = DateUtil.getMonthLastDay(month);
            query.setReceiveTime(monthFirstDay + "," + monthLastDay);
        }

        query.setShowProductId(productId);
        query.setPlat(Integer.valueOf(shopDRO.getPlat()));
        query.setWorkType(Arrays.asList(OrderConsts.ORDER_TYPE_NEW, OrderConsts.ORDER_TYPE_REWORK));

        Integer orderCount = orderWorkListBService.countOrderWorkByQuery(query);
        logger.debug("[{}]后端产品查询销量数据[{}]", query, orderCount);
        OrderCountDRO orderCountDRO = new OrderCountDRO();
        orderCountDRO.setMonthOrderCount(orderCount);

        return ResponseDTO.success(orderCountDRO);
    }

    @Override
    public ResponseDTO<List<OrderCountShopDRO>> getOrderCountByShowProductIdAndShopId(OrderCountShopDIO orderCountShopDIO) {
        logger.debug("getOrderCountByShowProductIdAndShopId 收到请求 orderCountShopDIO[{}]", orderCountShopDIO);
        ValidateResult validateResult = ValidatorUtil.validator(orderCountShopDIO);
        if (!validateResult.isSuccess()) {
            logger.error("[{}] 参数错误：{}", TAG, validateResult.toString());
            return ResponseDTO.fail("提交参数错误：" + validateResult.toString());
        }

        ShopDIO shopDIO = new ShopDIO();
        shopDIO.setShopId(orderCountShopDIO.getShopId());
        com.zmn.common.dto.ResponseDTO<ShopDRO> shopResponse = shopRemoteService.getShop(shopDIO);
        if (!shopResponse.getStatusBool()) {
            return ResponseDTO.fail(shopResponse.getMessage());
        }
        ShopDRO shopDRO = shopResponse.getData();

        OrderWorkQuery query = new OrderWorkQuery();

        if (!Objects.isNull(orderCountShopDIO.getMonth())) {
            // 如果没提供月份，默认查当月
            String monthFirstDay = DateUtil.getMonthFirstDay(orderCountShopDIO.getMonth());
            String monthLastDay = DateUtil.getMonthLastDay(orderCountShopDIO.getMonth());
            query.setReceiveTime(monthFirstDay + "," + monthLastDay);
        }

        query.setPlat(Integer.valueOf(shopDRO.getPlat()));
        query.setWorkType(Arrays.asList(OrderConsts.ORDER_TYPE_NEW, OrderConsts.ORDER_TYPE_REWORK));

        List<OrderCountShopDRO> orderCountShopDROList = Lists.newArrayList();

        orderCountShopDIO.getProductIdList().forEach(productId -> {
            query.setShowProductId(productId);
            Integer orderCount = orderWorkListBService.countOrderWorkByQuery(query);
            logger.debug("[{}]后端产品查询销量数据[{}]", query, orderCount);
            OrderCountShopDRO orderCountDRO = new OrderCountShopDRO();
            orderCountDRO.setProductId(productId);
            orderCountDRO.setMonthOrderCount(orderCount);
            orderCountShopDROList.add(orderCountDRO);
        });

        return ResponseDTO.success(orderCountShopDROList);
    }

    @Override
    public ResponseDTO<Integer> getOrderCountByQuery(OrderCountQueryDIO orderCountQueryDIO) {
        logger.info("根据前台产品，查询订单数量入参数{}", JSON.toJSONString(orderCountQueryDIO));

        if (NumberUtil.isNullOrZero(orderCountQueryDIO.getShowProductId())) {
            return ResponseDTO.fail("提交参数错误：前台产品id不能为空。");
        }

        OrderWorkQuery query = new OrderWorkQuery();
        query.setPlatWork(orderCountQueryDIO.getPlat());
        query.setShowProductId(orderCountQueryDIO.getShowProductId());
        query.setServCategId(Lists.newArrayList(orderCountQueryDIO.getServCategId()));
        query.setWorkType(Arrays.asList(OrderConsts.ORDER_TYPE_NEW, OrderConsts.ORDER_TYPE_REWORK));

        // 处理下单时间
        if (Objects.nonNull(orderCountQueryDIO.getReceiveTimeStart())) {
            Date endTime = Objects.isNull(orderCountQueryDIO.getReceiveTimeEnd()) ? new Date() : orderCountQueryDIO.getReceiveTimeEnd();

            String startStr = DateUtil.dateFormatToString(orderCountQueryDIO.getReceiveTimeStart(), DateUtil.FORMAT_DEFAULT);
            String endStr = DateUtil.dateFormatToString(endTime, DateUtil.FORMAT_DEFAULT);
            query.setReceiveTime(startStr + "," + endStr);
        }

        Integer orderCount = orderWorkListBService.countOrderWorkByQuery(query);

        return ResponseDTO.success(orderCount, "成功");
    }

    @Override
    public ResponseDTO<Map<Integer, Integer>> getOrderCountByQuery2(OrderCountQueryDIO orderCountQueryDIO) {
        BoolQueryBuilder query = QueryBuilders.boolQuery()
                .filter(QueryBuilders.termQuery("platWork", orderCountQueryDIO.getPlat()))
                .filter(QueryBuilders.termQuery("servCategId", orderCountQueryDIO.getServCategId()))
                .filter(QueryBuilders.termsQuery("showProductId", orderCountQueryDIO.getShowProductIdList()));

        // 处理下单时间
        if (Objects.nonNull(orderCountQueryDIO.getReceiveTimeStart())) {
            Date endTime = Objects.isNull(orderCountQueryDIO.getReceiveTimeEnd()) ? new Date() : orderCountQueryDIO.getReceiveTimeEnd();

            String startStr = DateUtil.dateFormatToString(orderCountQueryDIO.getReceiveTimeStart(), DateUtil.FORMAT_DEFAULT);
            String endStr = DateUtil.dateFormatToString(endTime, DateUtil.FORMAT_DEFAULT);

            query.filter(QueryBuilders.rangeQuery("accountTime").gte(startStr).lte(endStr));
        }

        TermsAggregationBuilder termsAggr = AggregationBuilders.terms("showProductId").field("showProductId").size(10000);
        termsAggr.subAggregation(AggregationBuilders.count("orderCount").field("orderId"));

        NativeSearchQuery countQuery = new NativeSearchQueryBuilder()
                .withPageable(PageRequest.of(0, 1))
                .withQuery(query)
                .addAggregation(termsAggr)
                .build();

        Aggregations aggregations = orderWorkEsBService.getAggregationsByQuery(countQuery);
        ParsedLongTerms productTerm = aggregations.get("showProductId");
        List<? extends Terms.Bucket> productBuckets = productTerm.getBuckets();

        Map<Integer, Integer> resultMap = Maps.newHashMap();

        productBuckets.forEach(bucket -> {

            Integer showProductId = bucket.getKeyAsNumber().intValue();
            Integer count = (int)bucket.getDocCount();

            resultMap.put(showProductId, count);
        });

        return ResponseDTO.success(resultMap);
    }

    @Override
    public ResponseDTO<UserOrderInfoDRO> getUserOrderInfoByUserId(Set<Long> userIdList) {
        logger.info("getUserOrderInfoByUserId 收到请求 userIdList[{}]", userIdList);

        UserOrderInfoDRO userOrderInfo = new UserOrderInfoDRO();
        // 用户下单量（用户下单就+1）
        OrderWorkQuery query = new OrderWorkQuery();
        query.setUserIdList(Lists.newArrayList(userIdList));
        query.setWorkType(Lists.newArrayList(OrderConsts.ORDER_TYPE_REWORK, OrderConsts.ORDER_TYPE_NEW));
        Integer ordersCount = orderWorkListBService.countOrderWorkByQuery(query);
        userOrderInfo.setOrdersCount(ordersCount);

        // 成功单量（订单结果为成功的订单）
        //query.setWorkStatus(Lists.newArrayList(OrderStatusConsts.WORK_STATUS_INPUT));
        query.setWorkResultStatus(OrderStatusConsts.WORK_RESULT_SUCCESS);
        // 消费金额（订单结果为成功的消费金额）
        List<EsOrderWork> esOrderWorkList = orderWorkListBService.listPageOrderWorkByQuery(query);
        int payTotalAmount = esOrderWorkList.stream().mapToInt(e -> Optional.ofNullable(e.getTotalAmount()).orElse(GlobalConsts.NONE)).sum();
        userOrderInfo.setPayTotalAmount(payTotalAmount);
        userOrderInfo.setOrdersSuccessCount(esOrderWorkList.size());

        return ResponseDTO.success(userOrderInfo);
    }

    private WeixinOrderDetailDRO getWeixinOrderDetailDRO(OrderWork orderWork) {
        Long orderId = orderWork.getOrderId();

        List<OrderProduct> orderProductList = orderProductService.listOrderProductByOrderIdSrcMaster(orderId);
        OrderDetail orderDetail = orderDetailService.findOrderDetailByKeySrcMaster(orderId);

        WeixinOrderDetailDRO weixinOrderDetail = new WeixinOrderDetailDRO();
        weixinOrderDetail.setOrderId(orderId);
        int orderStatus = OrderStatusConsts.getOrderStatus(orderWork.getStatus(), orderWork.getResultStatus());
        weixinOrderDetail.setStatus(orderStatus);
        weixinOrderDetail.setStatusName(OrderGlobalConsts.getOrderStatusName(orderStatus));
        weixinOrderDetail.setDutyStatus(orderWork.getDutyStatus());
        weixinOrderDetail.setDutyTime(orderWork.getDutyTime());
        weixinOrderDetail.setCompleteTime(orderWork.getCompleteTime());
        weixinOrderDetail.setReceiveTime(orderWork.getReceiveTime());
        weixinOrderDetail.setCancelTime(orderWork.getCancelTime());
        weixinOrderDetail.setDepositTime(orderWork.getDepositTime());
        weixinOrderDetail.setPayTime(orderWork.getPayTime());
        weixinOrderDetail.setRefundTime(orderWork.getRefundTime());
        weixinOrderDetail.setCompleteRefundStatus(this.completeRefundStatus(orderWork));
        weixinOrderDetail.setPrepayTime(orderWork.getPrepayTime());
        weixinOrderDetail.setOriginalAmount(orderWork.getOriginalAmount());
        weixinOrderDetail.setTotalAmount(this.getTotalAmount(orderWork));
        weixinOrderDetail.setFactAmount(this.factAmount(orderWork));
        weixinOrderDetail.setPrepayAmount(orderWork.getPrepayAmount());
        weixinOrderDetail.setChannelPrepayAmount(orderWork.getChannelPrepayAmount());
        weixinOrderDetail.setDiscountAmount(orderWork.getDiscountAmount());
        weixinOrderDetail.setDepositAmount(this.getDepositAmount(orderWork));
        weixinOrderDetail.setMasterAmount(orderWork.getMasterAmount());
        weixinOrderDetail.setWaitPayAmount(this.getWaitPayAmount(orderWork));
        weixinOrderDetail.setMasterPayStatus(orderWork.getMasterPayStatus());
        weixinOrderDetail.setMasterId(orderWork.getMasterId());
        weixinOrderDetail.setMasterName(orderWork.getMasterName());
        weixinOrderDetail.setUserId(orderWork.getUserId());
        weixinOrderDetail.setUserName(orderDetail.getUserName());
        weixinOrderDetail.setWorkId(orderWork.getWorkId());
        weixinOrderDetail.setChannelId(orderWork.getChannelId());
        weixinOrderDetail.setType(orderWork.getType());
        weixinOrderDetail.setCityId(orderWork.getCityId());
        weixinOrderDetail.setStreet(orderDetail.getStreet());
        weixinOrderDetail.setAddress(orderDetail.getAddress());
        weixinOrderDetail.setUserPhone(orderDetail.getTelephone());
        weixinOrderDetail.setServCategId(orderWork.getServCategId());
        weixinOrderDetail.setLatitude(orderDetail.getLatitude());
        weixinOrderDetail.setLongitude(orderDetail.getLongitude());
        weixinOrderDetail.setPrepayStatus(orderWork.getPrepayStatus());
        weixinOrderDetail.setFinalPrice(orderWork.getFinalPrice());
        weixinOrderDetail.setRefundStatus(this.getRefundStatus(orderWork));
        weixinOrderDetail.setServItemType(orderWork.getServItemType());
        weixinOrderDetail.setDiscountActivityId(orderWork.getDiscountActivityId());
        weixinOrderDetail.setLateAmount(orderDiscountCalcBService.getLateAmount(orderWork.getOrderId(), orderWork.getDiscountActivityId()));
        // 预约时间文案说明
        if (orderWork.getDutyTime() != null) {
            weixinOrderDetail.setDutyTimeText(TimeTextUtil.getDutyText(orderWork.getDutyTime()));
        }
        // 产品信息
        List<OrderProductDRO> orderProductDROList = BeanMapper.mapList(orderProductList, OrderProductDRO.class);
        weixinOrderDetail.setOrderProductList(orderProductDROList);

        // 服务项信息
        try {
            List<ZsServiceItemVO> serviceItemVos = zsNormalOrderServiceItemBService.findServiceItemVo(orderId, orderWork.getWorkId());
            if (!CollectionUtils.isEmpty(serviceItemVos)) {
                List<OrderServiceItem> orderServiceItems = new LinkedList<>();
                for (ZsServiceItemVO obj : serviceItemVos) {
                    if (!CollectionUtils.isEmpty(obj.getServiceItemList())) {
                        orderServiceItems.addAll(obj.getServiceItemList());
                    }
                }
                List<OrderServiceItemDRO> orerServiceItemDRO = BeanMapper.mapList(orderServiceItems, OrderServiceItemDRO.class);
                weixinOrderDetail.setOrderServiceItemList(orerServiceItemDRO);
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }

        // 评价信息
        OrderComment orderComment = orderCommentService.findCommentByKey(orderId);
        weixinOrderDetail.setComment(processOrderCommentDro(orderComment));

        // 订单优惠明细
        List<OrderDiscount> discountList = zsOrderDiscountBService.listByOrderId(orderId);
        List<OrderDetailDiscountDRO> orderDetailDiscountList = BeanMapper.mapList(discountList, OrderDetailDiscountDRO.class);
        if (CollectionUtil.isNotNullOrEmpty(orderDetailDiscountList)) {
            orderDetailDiscountList.forEach(e -> e.setCategName(StringUtils.defaultString(DiscountTypeEnums.getSubName(e.getCateg()))));

            // 优惠券 使用的优惠券、现金券、代金券换
            Integer discountCoupon = orderDetailDiscountList.stream().filter(e -> e.getCateg() != null && e.getAmount() != null && Lists.newArrayList(31, 32, 33).contains(e.getCateg())).mapToInt(e -> e.getAmount()).sum();
            weixinOrderDetail.setDiscountCoupon(discountCoupon);

            // 其他优惠
            Integer otherDiscount = orderDetailDiscountList.stream().filter(e -> e.getCateg() != null && e.getAmount() != null && !Lists.newArrayList(11, 21, 31, 32, 33).contains(e.getCateg())).mapToInt(e -> e.getAmount()).sum();
            weixinOrderDetail.setOtherDiscount(otherDiscount);
        }
        weixinOrderDetail.setOrderDiscountList(orderDetailDiscountList);

        // 返修次数
        Integer reworkCount = orderWorkListBService.countReworkSuccessByWorkId(orderWork.getOrderId(), orderWork.getWorkId());
        weixinOrderDetail.setReworkThirdTime(reworkCount);

        // 派单标示（是否存在多次派单，派单撤回算多次）
        OrderChangeRecord changeRecord = orderChangeRecordService.getChangeRecordByOrderId(orderWork.getOrderId());
        if (Objects.nonNull(changeRecord)) {
            if ((changeRecord.getFirstDistributeTime() != null && NumberUtil.isNullOrZero(orderWork.getMasterId())) || changeRecord.getDistributeCount() > 0) {
                weixinOrderDetail.setMultipleDistribute(GlobalConsts.YES);
            } else {
                weixinOrderDetail.setMultipleDistribute(GlobalConsts.NO);
            }
        }

        // 是否已取消
        CancelApplyResultBO waitCancelInfo = cancelApplyBService.getWaitCancelInfo(orderWork.getOrderId(), orderWork.getWorkId());
        if (Objects.equals(waitCancelInfo.getUserWaitCancelStatus(), GlobalConsts.YES)) {
            weixinOrderDetail.setWaitCancel(GlobalConsts.YES);
            weixinOrderDetail.setCancelTime(waitCancelInfo.getCanelApplyTime());
        }else {
            OrderWorkTrack orderWorkTrack = workTrackBService.getUserWaitCancelTrack(orderWork);
            if (orderWorkTrack != null) {
                weixinOrderDetail.setWaitCancel(GlobalConsts.YES);
                weixinOrderDetail.setCancelTime(orderWorkTrack.getCreateTime());
            }
        }

        // 是否为三日退订单
        weixinOrderDetail.setThreeDaysRefund(isThreeDaysRefund(orderWork));
        return weixinOrderDetail;
    }

    /**
     * 订单是否为三日退订单
     * @param orderWork
     * @return
     */
    private Integer isThreeDaysRefund(OrderWork orderWork){
        logger.info("ZsNormalOrderWorkRemoteServiceImpl.isThreeDaysRefund orderId={}", orderWork.getOrderId());
        try {
            logger.info("#oms#工单={},是否是三日无忧退工单，入参：channelId: {}, cityId:{}, servCategId:{}, showCategId:{}", orderWork.getOrderId(), orderWork.getChannelId(), orderWork.getCityId(), orderWork.getServCategId(), orderWork.getShowCategId());
            PilotCheckQuery query = new PilotCheckQuery();
            query.setPilotTypeId(PilotTypeEnum.THREE_DAY_RETREAT.getId());
            query.setCategId(orderWork.getShowCategId());
            query.setServCategId(orderWork.getServCategId());
            query.setChannelId(orderWork.getChannelId());
            query.setCityId(orderWork.getCityId());
            ResponseDTO<Boolean> responseDTO = pilotRemoteService.checkPilotByQuery(query);
            logger.info("#oms#工单={},是否是三日无忧退工单，出参={}", orderWork.getOrderId(), JSON.toJSONString(responseDTO));
            if (responseDTO.isSuccess() && responseDTO.getData()) {
                return GlobalConsts.YES;
            }
        } catch (Exception ex) {
            logger.error(String.format("订单号%s，获取是否是三日无忧退checkSupportByChannelIdAndCityIdAndTypeAndCategId接口异常了:%s", orderWork.getOrderId(), ex.getMessage()), ex);
            return GlobalConsts.NO;
        }
        return GlobalConsts.NO;
    }


    /**
     * 获取实付金额
     * @param orderWork
     * @return
     */
    private Integer factAmountFromEsOrder(EsOrderWork orderWork) {
        Integer factAmount = null;
        if (Objects.equals(orderWork.getChannelPrepayStatus(), PayConsts.PAY_STATUS_DONE) && !NumberUtil.isNullOrZero(orderWork.getChannelPrepayAmount())) {
            factAmount = Optional.ofNullable(factAmount).orElse(0) + orderWork.getChannelPrepayAmount();
        }
        if (Objects.equals(orderWork.getPrepayStatus(), PayConsts.PAY_STATUS_DONE) && !NumberUtil.isNullOrZero(orderWork.getPrepayAmount())) {
            factAmount = Optional.ofNullable(factAmount).orElse(0) + orderWork.getPrepayAmount();
        }
        if (Objects.equals(orderWork.getDepositStatus(), PayConsts.PAY_STATUS_DONE) && !NumberUtil.isNullOrZero(orderWork.getDepositAmount())) {
            factAmount = Optional.ofNullable(factAmount).orElse(0) + orderWork.getDepositAmount();
        }
        // TODO lujia 支付状态支付成功 代表尾款已经支付
        if (Objects.equals(orderWork.getPayStatus(), PayConsts.PAY_STATUS_DONE) && !NumberUtil.isNullOrZero(orderWork.getMasterAmount())) {
            factAmount = Optional.ofNullable(factAmount).orElse(0) + orderWork.getMasterAmount();
        }
        return factAmount;
    }

    /**
     * 获取实付金额
     * @param orderWork
     * @return
     */
    private Integer factAmount(OrderWork orderWork) {
        Integer factAmount= getDepositAmount(orderWork);

        if (Objects.equals(orderWork.getMasterPayStatus(), PayConsts.PAY_STATUS_DONE) && !NumberUtil.isNullOrZero(orderWork.getMasterAmount())) {
            factAmount = Optional.ofNullable(factAmount).orElse(0) + orderWork.getMasterAmount();
        }
        return factAmount;
    }

    /**
     * 获取已付定金
     *
     * @param orderWork
     * @return
     */
    private Integer getDepositAmount(OrderWork orderWork) {
        Integer depositAmount = null;
        if (Objects.equals(orderWork.getChannelPrepayStatus(), PayConsts.PAY_STATUS_DONE) && !NumberUtil.isNullOrZero(orderWork.getChannelPrepayAmount())) {
            depositAmount = Optional.ofNullable(depositAmount).orElse(0) + orderWork.getChannelPrepayAmount();
        }
        if (Objects.equals(orderWork.getPrepayStatus(), PayConsts.PAY_STATUS_DONE) && !NumberUtil.isNullOrZero(orderWork.getPrepayAmount())) {
            depositAmount = Optional.ofNullable(depositAmount).orElse(0) + orderWork.getPrepayAmount();
        }
        if (Objects.equals(orderWork.getDepositStatus(), PayConsts.PAY_STATUS_DONE) && !NumberUtil.isNullOrZero(orderWork.getDepositAmount())) {
            depositAmount = Optional.ofNullable(depositAmount).orElse(0) + orderWork.getDepositAmount();
        }
        return depositAmount;
    }

    /**
     * 待支付
     *
     * @param orderWork
     * @return
     */
    private Integer getWaitPayAmount(OrderWork orderWork) {
        Integer waitPayAmount = null;
        // 取消状态
        List<Integer> resultStatusList = Lists.newArrayList(OrderStatusConsts.WORK_RESULT_FAIL, OrderStatusConsts.WORK_RESULT_DISCARD);
        // 未取消/失败
        boolean resultStatusSupport = !resultStatusList.contains(orderWork.getResultStatus());
        // 未完成
        boolean isComplete = orderWork.getCompleteTime() == null;
        // 未取消 未完成 待支付
        if (Objects.equals(PayConsts.PAY_STATUS_ING, orderWork.getPrepayStatus()) && resultStatusSupport && isComplete) {
            waitPayAmount = orderWork.getPrepayAmount();
            return waitPayAmount;
        }

        // 定金未支付
        if (!NumberUtil.isNullOrZero(orderWork.getDepositAmount()) && orderWork.getDepositTime() == null) {
            waitPayAmount = Optional.ofNullable(waitPayAmount).orElse(0) + orderWork.getDepositAmount();
        }
        // 师傅收款额度
        if (!Objects.equals(orderWork.getMasterPayStatus(), PayConsts.PAY_STATUS_DONE) && !NumberUtil.isNullOrZero(orderWork.getMasterAmount())) {
            waitPayAmount = Optional.ofNullable(waitPayAmount).orElse(0) + orderWork.getMasterAmount();
        }
        return waitPayAmount;
    }

    /**
     * 处理完成前退款标示 （申请退款和退款完成都属于 完成前退款）
     *
     * @return
     */
    private Integer completeRefundStatus(OrderWork orderWork) {
        // 审核中，退款中
        if (Objects.equals(orderWork.getRefundReviewStatus(), OrderConsts.REVIEW_STATUS_DOING)) {
            return GlobalConsts.NO;
        }

        // 退款成功
        if (Objects.equals(orderWork.getRefundReviewStatus(), OrderConsts.REVIEW_STATUS_SUCCESS)) {
            return GlobalConsts.NO;
        }

        if (Objects.equals(orderWork.getPrepayStatus(), PayConsts.PAY_STATUS_DONE) && !NumberUtil.isNullOrZero(orderWork.getPrepayAmount())) {
            if (orderWork.getRefundTime() != null) {
                return GlobalConsts.NO;
            }
        }

        return GlobalConsts.NONE;
    }

    /**
     * 处理退款状态
     *
     * @return
     */
    private Integer getRefundStatus(OrderWork orderWork) {
        Integer refundStatus = OrderConsts.getUserRefundStatus(NumberUtil.isNotNullOrZero(orderWork.getRefundTargetWorkId()), orderWork.getRefundReviewStatus(), orderWork.getPayStatus());
        if (Objects.equals(orderWork.getPrepayStatus(), PayConsts.PAY_STATUS_DONE) && !NumberUtil.isNullOrZero(orderWork.getPrepayAmount())) {
            if (orderWork.getRefundTime() != null) {
                refundStatus = PayConsts.REFUND_STATUS_DONE;
            }
        }
        return refundStatus;
    }

    /**
     * 获取实付金额
     * @param orderWork
     * @return
     */
    private Integer getTotalAmount(OrderWork orderWork) {
        return orderWork.getTotalAmount();
    }

    private OrderCommentDRO processOrderCommentDro(OrderComment orderComment){
        if (Objects.isNull(orderComment)) {
            return null;
        }
        OrderCommentDRO comment = new OrderCommentDRO();
        comment.setScore(orderComment.getScore());
        comment.setAppendContent(orderComment.getAppendContent());
        comment.setAppendTime(orderComment.getAppendTime());
        comment.setContent(orderComment.getContent());
        comment.setTypeName(OrderConsts.getCommentTypeName(orderComment.getType()));
        comment.setCommentTime(orderComment.getCreateTime());
        comment.setReplyContent(orderComment.getReplyContent());
        if (CollectionUtil.isNotNullOrEmpty(orderComment.getDetailList())) {
            List<String> commentDetailList = Lists.newArrayList();
            orderComment.getDetailList().forEach(e -> commentDetailList.add(e.getMapName()));
            comment.setCommentDetailList(commentDetailList);
        }
        return comment;
    }
}
